package org.springrain.javadoc4openapi;

import com.thoughtworks.qdox.library.SortedClassLibraryBuilder;
import com.thoughtworks.qdox.model.JavaClass;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * 读取java源代码文件
 *
 * @author springrain
 * @version 0.0.1
 * @since 0.0.1
 */
public class JavaSourceUtils {
    private static final Logger logger = LoggerFactory.getLogger(JavaSourceUtils.class);
    private final static String mavenJavaPath = "src/main/java";

    private JavaSourceUtils() {
    }

    /**
     * 列出Maven项目下面的java file
     *
     * @return 返回maven项目的java源文件
     */
    static List<File> listProjectJavaFile() {
        return listProjectJavaFile(mavenJavaPath);
    }

    /**
     * 列出指定路径下的java file 文件
     *
     * @param path 路径
     * @return 返回指定路径下的java源文件
     */
    static List<File> listProjectJavaFile(String path) {
        // 所有的Java源文件
        List<File> allJavaFile = new ArrayList<>();
        try {
            // 获取 maven java的源文件的路径
            File file = new File(path);
            // 如果路径不存在,不是标准的Maven项目,获取项目的根目录
            if (!file.exists()) {
                file = new File("");
            }
            // 获取文件路径
            file = file.getAbsoluteFile();

            // 获取目录下的所有文件
            File[] allFile = file.listFiles();
            // 用于递归处理文件
            Stack<File> stack = new Stack<>();
            if (allFile != null) {
                for (File tmp : allFile) {
                    stack.push(tmp);
                }
            }
            while (!stack.isEmpty()) {
                File tmpFile = stack.pop();
                if (tmpFile.isDirectory()) {
                    File[] files = tmpFile.listFiles();
                    if (files != null)
                        for (File tmp : files) {
                            stack.push(tmp);
                        }
                    continue;
                }
                // .java 结尾的源文件,添加到 allJavaFile
                if (StringUtils.endsWith(tmpFile.getName(), ".java")) {
                    allJavaFile.add(tmpFile);
                }

            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return allJavaFile;
    }


    /**
     * 根据Jar包获取里面的.java文件的List<JavaClass>对象
     *
     * @param file jar文件
     * @return jar包文件里的Java源文件
     * @throws IOException 读取异常
     */
    public static List<JavaClass> loadJarFile(File file) throws IOException {
        return loadJarFile(file, null);
    }

    /**
     * 根据Jar包获取里面的.java文件的List<JavaClass>对象
     *
     * @param file        jar文件
     * @param classLoader 加载器
     * @return jar包文件里的Java源文件
     * @throws IOException 读取异常
     */
    public static List<JavaClass> loadJarFile(File file, ClassLoader classLoader) throws IOException {
        SortedClassLibraryBuilder classLibraryBuilder = new SortedClassLibraryBuilder();
        if (classLoader != null) {
            classLibraryBuilder.appendClassLoader(classLoader);
        } else {
            classLibraryBuilder.appendDefaultClassLoaders();
        }

        try (JarFile jarFile = new JarFile(file)) {
            for (Enumeration<?> entries = jarFile.entries(); entries.hasMoreElements(); ) {
                JarEntry entry = (JarEntry) entries.nextElement();

                String name = entry.getName().toLowerCase();
                if (name.endsWith(".java") && !name.endsWith("package-info.java")) {
                    try (InputStream in = jarFile.getInputStream(entry)) {
                        classLibraryBuilder.addSource(new InputStreamReader(in, "utf-8"));
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }


        return new ArrayList<>(classLibraryBuilder.getClassLibrary().getJavaClasses());
    }


    /**
     * 根据java类文件List,获取List<JavaClass>对象
     *
     * @param classList java类文件
     * @return Java源码文件
     */
    static List<JavaClass> readJavaFiles(List<File> classList) {
        List<JavaClass> result = new ArrayList<>();
        if (CollectionUtils.isEmpty(classList)) {
            return result;
        }
        SortedClassLibraryBuilder classLibraryBuilder = new SortedClassLibraryBuilder();
        classLibraryBuilder.appendDefaultClassLoaders();
        for (File file : classList) {
            try {
                classLibraryBuilder.addSource(file);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }

        }
        return new ArrayList<>(classLibraryBuilder.getClassLibrary().getJavaClasses());

    }

    /**
     * 把JavaClass的List转成Map,使用类的全路径做key
     *
     * @param classList java文件列表
     * @return java全路径为key, JavaClass为Value
     */
    public static Map<String, JavaClass> transforJavaClass(List<JavaClass> classList) {
        Map<String, JavaClass> javaClassMap = new HashMap<>();
        for (JavaClass javaClass : classList) {
            javaClassMap.put(javaClass.getFullyQualifiedName(), javaClass);
        }
        return javaClassMap;
    }
}
